import httpx
from typing import List, Dict, Any, Optional
from loguru import logger
from app.core.config import settings
from app.schemas.deepseek import ChatRequest, PromptRequest, ApiResponse, ErrorResponse, Message
from fastapi import HTTPException
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import json
import os
import asyncio
from datetime import datetime

class DeepSeekApiError(Exception):
    """DeepSeek API 错误"""
    def __init__(self, code: int, message: str, details: Optional[Dict] = None):
        self.code = code
        self.message = message
        self.details = details
        super().__init__(message)

class DeepSeekService:
    """
    DeepSeek API服务类
    通过硅基流动平台调用DeepSeek模型
    """
    def __init__(self):
        self._validate_api_key()
        self.api_base = settings.DEEPSEEK_API_BASE
        self.model = "deepseek-ai/DeepSeek-R1"
        self.timeout = httpx.Timeout(
            timeout=120.0,  # 总超时时间
            connect=60.0,   # 连接超时
            read=120.0,     # 读取超时
            write=60.0,     # 写入超时
            pool=None       # 连接池超时
        )
        
    def _validate_api_key(self):
        """验证 API 密钥"""
        if not settings.DEEPSEEK_API_KEY:
            raise DeepSeekApiError(
                code=401,
                message="未配置 DeepSeek API 密钥",
                details={"help": "请在环境变量中设置 DEEPSEEK_API_KEY"}
            )
        self.api_key = settings.DEEPSEEK_API_KEY
        
    def _handle_api_error(self, e: httpx.HTTPError) -> None:
        """处理 API 错误"""
        error_map = {
            401: "API 密钥无效",
            403: "没有访问权限",
            404: "请求的资源不存在",
            429: "请求太频繁，请稍后重试",
            500: "服务器内部错误",
            503: "服务暂时不可用"
        }
        
        status_code = getattr(e.response, "status_code", 500)
        error_msg = error_map.get(status_code, "未知错误")
        
        try:
            error_detail = e.response.json()
        except:
            error_detail = {"error": str(e)}
            
        raise DeepSeekApiError(
            code=status_code,
            message=error_msg,
            details=error_detail
        )
        
    @retry(
        stop=stop_after_attempt(3),  # 最多重试3次
        wait=wait_exponential(multiplier=1, min=4, max=10),  # 指数退避重试
        retry=retry_if_exception_type((httpx.TimeoutException, httpx.HTTPError))  # 仅在超时和HTTP错误时重试
    )
    async def generate_completion(self, request: ChatRequest) -> ApiResponse:
        """
        生成AI回复
        
        Args:
            request: 对话请求
            
        Returns:
            API响应结果
        """
        try:
            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            }
            
            payload = request.dict()
            payload["model"] = self.model
            
            async with httpx.AsyncClient(timeout=self.timeout) as client:
                response = await client.post(
                    f"{self.api_base}/chat/completions",
                    headers=headers,
                    json=payload
                )
                response.raise_for_status()
                result = response.json()
                
                return ApiResponse(
                    code=200,
                    message="success",
                    data=result,
                    timestamp=datetime.utcnow()
                )
                
        except httpx.TimeoutException as e:
            logger.error(f"请求超时: {str(e)}")
            raise DeepSeekApiError(
                code=408,
                message="请求超时",
                details={"error": str(e)}
            )
        except httpx.HTTPError as e:
            logger.error(f"HTTP错误: {str(e)}")
            self._handle_api_error(e)
        except Exception as e:
            logger.error(f"未知错误: {str(e)}")
            raise DeepSeekApiError(
                code=500,
                message="服务器内部错误",
                details={"error": str(e)}
            )
            
    async def generate_prompt(self, request: PromptRequest) -> ApiResponse:
        """
        生成提示词
        
        Args:
            request: 提示词请求
            
        Returns:
            生成的提示词结果
        """
        system_prompt = (
            "你是一个专业的AI视频提示词专家。"
            "请将用户的中文描述转换为规范的英文提示词。"
            f"请使用{request.prompt_type.upper()}模式生成提示词。"
        )
        
        chat_request = ChatRequest(
            messages=[
                Message(role="system", content=system_prompt),
                Message(role="user", content=request.text)
            ],
            temperature=request.temperature,
            max_tokens=request.max_tokens
        )
        
        response = await self.generate_completion(chat_request)
        
        # 提取生成的提示词
        if response.data and "choices" in response.data:
            prompt = response.data["choices"][0]["message"]["content"]
            return ApiResponse(
                code=200,
                message="success",
                data={"prompt": prompt},
                timestamp=datetime.utcnow()
            )
        else:
            raise DeepSeekApiError(
                code=500,
                message="提示词生成失败",
                details={"error": "API 响应格式错误"}
            ) 